#include "SaveGameState.h"
#include "OptionsState.h"
#include "GameState.h"
#include "../Game.h"
#include "../SGD Wrappers/SGD_InputManager.h"
#include "../Font.h"
#include "../TinyXML/tinyxml.h"

CSaveGameState* CSaveGameState::GetInstance(void)
{
	static CSaveGameState s_Instance;

	return &s_Instance;
}

void CSaveGameState::Enter(void)
{
	Load(-1);
}
void CSaveGameState::Exit(void)
{

}

bool CSaveGameState::Input(void)
{
	SGD::InputManager* pInput = SGD::InputManager::GetInstance();

	if ((pInput->IsButtonPressed(0, 0) == true || pInput->IsKeyPressed(SGD::Key::Enter) == true) && m_nCursor == 0)
		m_eState = SAVE;

	if ((pInput->IsButtonPressed(0, 0) == true || pInput->IsKeyPressed(SGD::Key::Enter) == true) && m_nCursor == 1)
	{
		m_eState = LOAD;
		m_nCursor = 0;
	}

	switch (m_eState)
	{
	case SAVE:
	{
				 if (pInput->IsKeyPressed(SGD::Key::Escape) == true)
					 m_eState = DEFAULT;
				 if (pInput->IsKeyPressed(SGD::Key::Enter) == true)
				 {
					 Save(m_nSaveCursor);
				 }
				 break;
	}
	case LOAD:
	{
				 if (pInput->IsKeyPressed(SGD::Key::Escape) == true)
					 m_eState = DEFAULT;
				 if (pInput->IsKeyPressed(SGD::Key::Enter) == true)
					 Load(m_nLoadCursor);
				 break;
	}
	case DEFAULT:
	{
					if (pInput->IsKeyPressed(SGD::Key::Escape) == true ||
						pInput->IsButtonPressed(0, 1) == true ||
						(pInput->IsKeyPressed(SGD::Key::Enter) == true && m_nCursor == 2))
					{
						Game::GetInstance()->ChangeState(COptionsState::GetInstance());
						return true;
					}
					break;
	}
	}

	if (m_eState == DEFAULT)
	{
		if (pInput->IsKeyPressed(SGD::Key::Down) == true ||
			pInput->IsDPadPressed(0, SGD::DPad::Down) == true)
		{
			++m_nCursor;

			// Wrap around
			if (m_nCursor > 2)
				m_nCursor = 0;
		}
		else if (pInput->IsKeyPressed(SGD::Key::Up) == true ||
			pInput->IsDPadPressed(0, SGD::DPad::Up) == true)
		{
			--m_nCursor;

			// Wrap around
			if (m_nCursor < 0)
				m_nCursor = 2;
		}
	}

	if (m_eState == SAVE)
	{
		if (pInput->IsKeyPressed(SGD::Key::Down) == true ||
			pInput->IsDPadPressed(0, SGD::DPad::Down) == true)
		{
			++m_nSaveCursor;

			// Wrap around
			if (m_nSaveCursor > 2)
				m_nSaveCursor = 0;
		}
		else if (pInput->IsKeyPressed(SGD::Key::Up) == true ||
			pInput->IsDPadPressed(0, SGD::DPad::Up) == true)
		{
			--m_nSaveCursor;

			// Wrap around
			if (m_nSaveCursor < 0)
				m_nSaveCursor = 2;
		}
	}

	if (m_eState == LOAD)
	{
		if (pInput->IsKeyPressed(SGD::Key::Down) == true ||
			pInput->IsDPadPressed(0, SGD::DPad::Down) == true)
		{
			++m_nLoadCursor;

			// Wrap around
			if (m_nLoadCursor > 2)
				m_nLoadCursor = 0;
		}
		else if (pInput->IsKeyPressed(SGD::Key::Up) == true ||
			pInput->IsDPadPressed(0, SGD::DPad::Up) == true)
		{
			--m_nLoadCursor;

			// Wrap around
			if (m_nLoadCursor < 0)
				m_nLoadCursor = 2;
		}
	}

	return true;
}

void CSaveGameState::Update(float elapsedTime)
{
	m_fInputDelay += elapsedTime;
}

void CSaveGameState::Render(void)
{
	const Font* pFont = Game::GetInstance()->GetFont();

	Game* pGame = Game::GetInstance();

	float darkOffset = pGame->DarkOff();
	float medOffset = pGame->MedOff();
	float lightOffset = pGame->LightOff();

	SGD::GraphicsManager::GetInstance()->DrawTexture(pGame->GetDarkSmoke(), { darkOffset, 0 }, 0.0f, { 0, 0 }, { 150, 255, 255, 255 });
	SGD::GraphicsManager::GetInstance()->DrawTexture(pGame->GetMedSmoke(), { medOffset, 0 }, 0.0f, { 0, 0 }, { 127, 255, 255, 255 });
	SGD::GraphicsManager::GetInstance()->DrawTexture(pGame->GetLightSmoke(), { lightOffset, 0 }, 0.0f, { 0, 0 }, { 90, 255, 255, 255 });

	SGD::GraphicsManager::GetInstance()->DrawTexture(pGame->GetDarkSmoke(), { darkOffset - 805, 0 }, 0.0f, { 0, 0 }, { 150, 255, 255, 255 });
	SGD::GraphicsManager::GetInstance()->DrawTexture(pGame->GetMedSmoke(), { medOffset - 805, 0 }, 0.0f, { 0, 0 }, { 127, 255, 255, 255 });
	SGD::GraphicsManager::GetInstance()->DrawTexture(pGame->GetLightSmoke(), { lightOffset - 805, 0 }, 0.0f, { 0, 0 }, { 90, 255, 255, 255 });

	switch (m_eState)
	{
	case DEFAULT:
	{
					pFont->Draw("Save or Load", { 75, 1 }, 1, { 255, 255, 255 });
					if (m_nCursor == 0)
						pFont->Draw("Save", { 0, 100 }, 1, { 0, 255, 0 });
					else
						pFont->Draw("Save", { 0, 100 }, 1, { 255, 255, 255 });

					if (m_nCursor == 1)
						pFont->Draw("Load", { 0, 200 }, 1, { 0, 255, 0 });
					else
						pFont->Draw("Load", { 0, 200 }, 1, { 255, 255, 255 });

					if (m_nCursor == 2)
						pFont->Draw("Exit", { 0, 300 }, 1, { 0, 255, 0 });
					else
						pFont->Draw("Exit", { 0, 300 }, 1, { 255, 255, 255 });
	}
		break;
	case SAVE:
	{
				 pFont->Draw("Save", { 200, 1 }, 1, { 255, 255, 255 });
				 if (m_nSaveCursor == 0)
					 pFont->Draw("Slot One", { 0, 100 }, 1, { 0, 255, 0 });
				 else
					 pFont->Draw("Slot One", { 0, 100 }, 1, { 255, 255, 255 });

				 if (m_nSaveCursor == 1)
					 pFont->Draw("Slot Two", { 0, 200 }, 1, { 0, 255, 0 });
				 else
					 pFont->Draw("Slot Two", { 0, 200 }, 1, { 255, 255, 255 });

				 if (m_nSaveCursor == 2)
					 pFont->Draw("Slot Three", { 0, 300 }, 1, { 0, 255, 0 });
				 else
					 pFont->Draw("Slot Three", { 0, 300 }, 1, { 255, 255, 255 });
	}
		break;
	case LOAD:
	{
				 pFont->Draw("Load", { 200, 1 }, 1, { 255, 255, 255 });
				 if (m_nLoadCursor == 0)
					 pFont->Draw("Slot One", { 0, 100 }, 1, { 0, 255, 0 });
				 else
					 pFont->Draw("Slot One", { 0, 100 }, 1, { 255, 255, 255 });

				 if (m_nLoadCursor == 1)
					 pFont->Draw("Slot Two", { 0, 200 }, 1, { 0, 255, 0 });
				 else
					 pFont->Draw("Slot Two", { 0, 200 }, 1, { 255, 255, 255 });

				 if (m_nLoadCursor == 2)
					 pFont->Draw("Slot Three", { 0, 300 }, 1, { 0, 255, 0 });
				 else
					 pFont->Draw("Slot Three", { 0, 300 }, 1, { 255, 255, 255 });
	}
		break;
	}
}

void CSaveGameState::Save(int slot)
{
	// Create a tiny XML doc
	TiXmlDocument doc;

	// Allocate a declaration
	TiXmlDeclaration* pDec = new TiXmlDeclaration("1.0", "utf-8", "");

	// Attach the Dec to the Doc
	doc.LinkEndChild(pDec);

	// Allocate the root
	TiXmlElement* pRoot = new TiXmlElement("Saves");

	// Attach the root to the doc
	doc.LinkEndChild(pRoot);

	// Allocate the first save slot
	TiXmlElement* pSlotOne = new TiXmlElement("Slot_1");

	if (slot == 0)
	{
		redOne = tempRed;
		blueOne = tempBlue;
	}
	else if (slot == 1)
	{
		redTwo = tempRed;
		blueTwo = tempBlue;
	}
	else if (slot == 2)
	{
		redThree = tempRed;
		blueThree = tempBlue;
	}

	// Set SlotOne's attributes
	pSlotOne->SetAttribute("Red_Score", redOne);
	pSlotOne->SetAttribute("Blue_Score", blueOne);

	// Attach to SlotOne to the root
	pRoot->LinkEndChild(pSlotOne);

	// Allocate the second save slot
	TiXmlElement* pSlotTwo = new TiXmlElement("Slot_2");

	// Set SlotTwo's attributes
	pSlotTwo->SetAttribute("Red_Score", redTwo);
	pSlotTwo->SetAttribute("Blue_Score", blueTwo);

	// Attach to SlotTwo to the root
	pRoot->LinkEndChild(pSlotTwo);

	// Allocate the third save slot
	TiXmlElement* pSlotThree = new TiXmlElement("Slot_3");

	// Set SlotThree's attributes
	pSlotThree->SetAttribute("Red_Score", redThree);
	pSlotThree->SetAttribute("Blue_Score", blueThree);

	// Attach to SlotThree to the root
	pRoot->LinkEndChild(pSlotThree);

	// Get the filepath to the AppData folder
	std::string filePath = Game::GetInstance()->GetSavePath();
	filePath += "Saves.xml";

	// Write the doc to the file
	doc.SaveFile(filePath.c_str());
}

void CSaveGameState::Load(int slot)
{
	// Create the doc
	TiXmlDocument doc;

	// Get the filepath to the AppData folder
	std::string filePath = Game::GetInstance()->GetSavePath();
	filePath += "Saves.xml";

	// try to load the file
	if (doc.LoadFile(filePath.c_str()) == false)
		return;

	// Get the root
	TiXmlElement* pRoot = doc.RootElement();

	// Check if it's valid
	if (pRoot == nullptr)
		return;

	// Get the elements within the saved file
	TiXmlElement* pLoadSlotOne = pRoot->FirstChildElement("Slot_1");
	TiXmlElement* pLoadSlotTwo = pRoot->FirstChildElement("Slot_2");
	TiXmlElement* pLoadSlotThree = pRoot->FirstChildElement("Slot_3");

	// Assign the scores as necessary
	pLoadSlotOne->Attribute("Red_Score", &redOne);
	pLoadSlotOne->Attribute("Blue_Score", &blueOne);

	pLoadSlotTwo->Attribute("Red_Score", &redTwo);
	pLoadSlotTwo->Attribute("Blue_Score", &blueTwo);

	pLoadSlotThree->Attribute("Red_Score", &redThree);
	pLoadSlotThree->Attribute("Blue_Score", &blueThree);

	// Assign the scores corresponding with the selected slot

	if (slot == 0)
	{
		CGameState::GetInstance()->SetRedScore(redOne);
		CGameState::GetInstance()->SetBlueScore(blueOne);
	}
	else if (slot == 1)
	{
		CGameState::GetInstance()->SetRedScore(redTwo);
		CGameState::GetInstance()->SetBlueScore(blueTwo);
	}
	else if (slot == 2)
	{
		CGameState::GetInstance()->SetRedScore(redThree);
		CGameState::GetInstance()->SetBlueScore(blueThree);
	}
	else
		return;
}